import * as cc from "cc";
import LevelManager from "./LevelManager";
import { GlobalEnum } from "../../Script/GameSpecial/GlobalEnum";
import { EventType } from "../../Script/GameSpecial/GameEventType";
import GlobalPool, { customPoolScript } from "../../Script/Common/GlobalPool";
import LevelCamera from "./LevelCamera";
import GlobalData from "../../Script/Common/GlobalData";
import MapData from "../../Script/GameSpecial/MapData";
import GameConfig from "../../Script/GameSpecial/GameConfig";
import { RoadItem } from "./RoadItem";
import { BarrierGroup } from "./BarrierGroup";
import { Role } from "./Role";
import { BaseTransform } from "./BaseTransform";
import { GroundCarIcon } from "./GroundCarIcon";
import { ChangeCarQuad } from "./ChangeCarQuad";
import { Terrain } from "./Terrain";
import { TreeData } from "../../Script/GameSpecial/treeData";
import Loader from "../../Script/Common/Loader";
import { ScoreRoad } from "./ScoreRoad";
import { SceneStyle } from "../../Script/GameSpecial/SceneStyle";

const { ccclass, property } = cc._decorator;

@ccclass
export default class MyLevelManager extends LevelManager {

    /**************************************************通用流程**************************************************/
    //#region 
    public init() {
        this.initActMng();

        this.initAI();
        this.initAllCullItems();
        this.initBarrierGroups();
        this.initBarriers();
        this.initCaiDai();
        this.initCamera();
        this.initCarParts();
        this.initChangeCarQuads();
        this.initCustomUpdateState();
        this.initEnterLobbyState();
        this.initFinishDoor();
        this.initGolds();
        this.initGrade();
        this.initGroundCarIcon();
        this.initGroundLayer();
        this.initLevelTimer();
        this.initMats();
        this.initPartMat();
        this.initPlayer();
        this.initRoad();
        this.initScoreRoad();
        this.initStartLine();
        this.initStreaks();
        this.initSuiDao();
        this.initTerrains();

        this.loadLobbyItems();

        this.registAllCustomUpdate();
        this.onEvents();

    }
    protected registAllCustomUpdate() {
        //通用状态
        this.registCustomUpdate(GlobalEnum.LevelState.waitTrySkin, this.stepWaitTrySkin);
        this.registCustomUpdate(GlobalEnum.LevelState.playing, this.stepLevelPlaying);
        this.registCustomUpdate(GlobalEnum.LevelState.win, this.stepLevelWin);
        this.registCustomUpdate(GlobalEnum.LevelState.lose, this.stepLevelLose);
        this.registCustomUpdate(GlobalEnum.LevelState.lobby, this.stepLobby);
        this.registCustomUpdate(GlobalEnum.LevelState.fighting, this.stepPlayerFighting);

        //其他状态
        this.registCustomUpdate(GlobalEnum.LevelState.moveToScoreLine, this.stepMoveToScoreStartLine);
        this.registCustomUpdate(GlobalEnum.LevelState.moveOnScoreRoad, this.stepScoreRoad);

    }
    protected onEvents() {
        //游戏总流程相关
        this.on(EventType.Common.DirectorEvent.pauseLevel, this.pause, this);
        this.on(EventType.Common.DirectorEvent.resumeLevel, this.resume, this);

        this.on(EventType.LevelEvent.testLose, this.onTestLose, this);
        this.on(EventType.LevelEvent.testWin, this.onTestWin, this);

        this.on(EventType.LevelEvent.resurgence, this.onResurgence, this);

        //游戏玩法相关

        this.on(EventType.LevelEvent.addBarriers, this.addBarriers, this);
        this.on(EventType.LevelEvent.removeBarrier, this.removeBarrier, this);
        this.on(EventType.LevelEvent.removeBarrierGroup, this.removeBarrierGroup, this);
        this.on(EventType.LevelEvent.playerCollChangeCarQuad, this.onPlayerCollChangeCarQuad, this);
        this.on(EventType.LevelEvent.playerCollGold, this.onPlayerCollGold, this);
        this.on(EventType.LevelEvent.playerGetCarPart, this.onPlayerGetCarPart, this);
        this.on(EventType.LevelEvent.playerDropCarPart, this.onPlayerDropCarPart, this);
        this.on(EventType.LevelEvent.playerPartFull, this.onPlayerPartFull, this);
        this.on(EventType.LevelEvent.playerPartExitFull, this.onPlayerPartExitFull, this);
        this.on(EventType.LevelEvent.addCarStreak, this.addStreaks, this);
        this.on(EventType.LevelEvent.removeCarStreak, this.removeStreaks, this);
        this.on(EventType.LevelEvent.enemyArrived, this.onEnemyArrived, this);

        this.on(EventType.LevelEvent.showMapFast, this.onShowMapFast, this);
        this.on(EventType.LevelEvent.showMapSlow, this.onShowMapSlow, this);
    }
    /**加载进入首页时必须显示的内容 */
    protected loadLobbyItems() {

    }
    public reset() {
        this.resetAI();
        this.resetAllCullItems();
        this.resetBarrierGroups();
        this.resetBarriers();
        this.resetCarParts();
        this.resetCaiDai();
        this.resetCamera();
        this.resetChangeCarQuads();
        this.resetCustomUpdateState();
        this.resetFinishDoor();
        this.resetGolds();
        this.resetGrade();
        this.resetGroundCarIcon();
        this.resetGroundLayer();
        this.resetLevelTimer();
        this.resetMats();
        this.resetPartMat();
        this.resetPlayer();
        this.resetRoad();
        this.resetScoreRoad();
        this.resetSimpleComps();
        this.resetStartLine();
        this.resetStreaks();
        this.resetSuiDao();
        this.resetTerrains();
    }
    //#endregion

    //#region 关卡暂停/恢复
    protected isPaused: boolean;          //关卡是否暂停状态
    public get paused() { return this.isPaused; }
    protected pauseCount: number = 0;
    /**暂停关卡运行 */
    public pause(count: number = 1) {
        if (!this.paused) {
            //暂停动画播放
        }
        this.pauseCount += count;
        this.isPaused = true;
    }
    /**
     * 继续关卡运行
     * @param count 值为-1时强制恢复关卡运行
     */
    public resume(count: number = 1) {
        if (count === -1) {
            this.pauseCount = 0;
            this.isPaused = false;
        } else {
            this.pauseCount -= count;
            if (this.pauseCount <= 0) {
                this.pauseCount = 0;
                this.isPaused = false;
            }
        }
        if (!this.paused) {
            //恢复动画播放
        }

    }
    //#endregion

    /**************************************************对外功能**************************************************/
    //#region 进入关卡
    //进入关卡，设置关卡数据，启动关卡控制器，开始游戏
    public enterLevel(levelData) {
        this.node.active = true;
        if (this.needLoadCount <= 0) {
            // this.reset();
            this.levelData = levelData;
            this._enterLevel();
        } else {
            this.levelData = levelData;
            this.nextState = GlobalEnum.LevelState.playing;
        }
    }
    protected _enterLevel() {
        this.setData();
        this.backSpeed = this.totalRoadLen / 5;
        if (this.backSpeed < 200) {
            this.backSpeed = 200;
        }
        this.enterCustomUpdateState(GlobalEnum.LevelState.playing);
        this.showTouchMask();

        this.emit(EventType.Common.AudioEvent.playBGM, GlobalEnum.AudioClip.BGM, { isLoop: true, volume: 0.8 });
        let lv = this.levelData.lv;
        if (undefined === lv) {
            lv = this.levelData.id;
        }
        this.emit(EventType.Common.ALDEvent.levelStart, lv);
    }

    protected setData() {
        //关卡内容
        //敌人
        this.setAI([
            {
                z: 0,
                radian: 0.2,
            },
            {
                z: 0,
                radian: -0.2,
            },
            {
                z: 0,
                radian: -0.4,
            },
        ])
        //玩家
        this.setPlayer(null);
        this.player.enterLevel({
            z: 0,
            radian: 0.02,
        });

        //相机
        this.camera.setTarget(this.player.node);
        this.camera.enterLevel();
        this.canResurgence = true;
        // this.startCullItems(0);
    }
    //关卡内容
    protected preSceneStyleId: number = null;
    protected setLevelMapData() {
        if (this.preSceneStyleId !== null) {
            let id = MapData.getSceneStyleData().id;
            if (id !== this.preSceneStyleId) {
                let style = SceneStyle[this.preSceneStyleId];
                let shitou = style.ShiTouNames;
                for (let i = shitou.length - 1; i >= 0; --i) {
                    GlobalPool.clear(shitou[i]);
                }
                let trees = style.TreeNames;
                for (let i = trees.length - 1; i >= 0; --i) {
                    GlobalPool.clear(trees[i]);
                }
            }
        }
        this.preSceneStyleId = MapData.getSceneStyleData().id;
        //地图
        this.totalRoadLen = MapData.getTotalLen();
        this.setMatPathData(MapData.getMatData(), this.levelMats);
        this.setRoads(this.totalRoadLen);
        this.setEndLine();
        let data = MapData.getLevelItem();
        //隧道、红绿灯
        this.setSuiDao(data.suiDao);
        //终点
        this.setFinishDoor();
        this.setScoreRoad();
        //障碍物
        this.setBarrierGroups(data.leftBarrierGroups, "LeftBarrierGroup");
        this.setBarrierGroups(data.rightBarrierGroups, "RightBarrierGroup");
        this.setBarrierGroups(data.wallBarrierGroups, "WallBarrierGroup");
        this.setBarrierGroups(data.lunTaiGroups, "LunTaiGroup");
        this.addEndRoadBarrierGroup();
        this.allBarrierGroups.sort((a, b) => {
            return b.node.position.z - a.node.position.z;
        });
        // 零件
        this.setCarParts(data.carParts);
        this.setCarParts2(data.carParts2);
        this.allCarParts.sort((a, b) => {
            return b.node.position.z - a.node.position.z;
        });

        this.setGolds(data.golds);
        this.setTerrains(data.terrains);
        //车辆标志
        this.setGroundCarIcons(data.changeCarQuad);
        this.setChangeCarQuads(data.changeCarQuad);
        //石头和树
        let sceneStyle = MapData.getSceneStyleData();
        Loader.loadBundle(sceneStyle.bundle, () => {
            Loader.loadBundleDir(sceneStyle.bundle, "Prefab", (arr) => {
                for (let i = arr.length - 1; i >= 0; --i) {
                    GlobalPool.createPool(arr[i].data.name, arr[i]);
                }
                Loader.loadBundleDir(sceneStyle.bundle, "materials", (mats) => {
                    this.setMatPathData(MapData.getMatData(), mats);
                    this.setShiTou(data.shiTous);
                    this.setTrees(data.shiTous);
                    //记录全部动态显隐的物体
                    this.setAllCullItems(0);
                });
            });
        });

    }

    //#endregion

    //#region 教学脚本
    public setTeachCmp(js) {
    }
    //#endregion

    //#region 进入首页
    /**设置在首页中作为背景时需要显示的内容 */
    protected setEnterLobbyData() {
        this.setLevelMapData();
        this.lobbyCameraPosZ = 0;
        this.lobbySpeed = -Math.abs(this.lobbySpeed);
        this.lobbySpeedScale = 1;
        this.camera.moveTo(0, cc.v3(0, 0, 0));
    }
    //#endregion

    /**************************************************管理数据**************************************************/
    /**敌人出现的位置 */
    protected enemyEnterPos: cc.Vec3[] = [];

    /**关卡路段总长 */
    protected totalRoadLen: number;
    protected backSpeed: number = 200;

    //#region 玩家成绩
    /**玩家成绩 */
    protected grade: {
        /**拾取的金币 */
        gold: number,
        /**先于玩家到达终点站的敌人 */
        arrivedEnemyCount: number,
        /**金币倍率 */
        scoreRate: number,
    } = null;
    protected initGrade() {
        this.grade = {
            gold: 0,
            arrivedEnemyCount: 0,
            scoreRate: 1,
        };
    }
    protected resetGrade() {
        this.grade.gold = 0;
        this.grade.arrivedEnemyCount = 0;
        this.grade.scoreRate = 1;
    }
    protected addGradeGold() {
        this.grade.gold += 1;
        this.emit(EventType.LevelEvent.updateGold, this.grade.gold);
    }
    protected getResultData() {
        let data = {
            lv: this.levelData.lv,
            gold: this.grade.gold,
            scoreRate: this.getScoreRate(),
            mingCi: this.grade.arrivedEnemyCount + 1,
        };
        // if (this.grade.arrivedEnemyCount == 0) {
        //     data.gold += 100;
        // }
        if (data.scoreRate < 1) {
            data.scoreRate = 1;
        }
        return data;
    }
    //#endregion

    /**************************************************管理对象**************************************************/
    //#region 玩家
    @property(cc.Node)
    protected playerLayer: cc.Node = null;
    protected player: any = null;
    protected initPlayer() {
    }
    protected resetPlayer() {
        if (!!this.player) {
            GlobalPool.put(this.player.node);
            this.player = null;
            GlobalData.set(GlobalEnum.myGlobalDataType.player, null);
        }
    }
    protected setPlayer(data) {
        this.resetPlayer();
        let node = GlobalPool.get("Player");
        this.player = node[customPoolScript];
        this.playerLayer.addChild(node);
        GlobalData.set(GlobalEnum.myGlobalDataType.player, this.player);
    }
    protected updatePlayer(dt: number) {
        this.player.customUpdate(dt);
    }
    //#endregion

    //#region 相机
    @property(LevelCamera)
    protected camera: LevelCamera = null;
    protected initCamera() {
        this.camera.init();
        GlobalData.set(GlobalEnum.Common.GlobalDataType.levelCamera, this.camera);
    }
    protected resetCamera() {
        this.camera.reset();
    }
    protected updateCamera(dt: number) {
        this.camera.customUpdate(dt);
    }
    //#endregion

    //#region 用于坐标转换的相机
    @property(cc.Node)
    protected transformCameraNode: cc.Node = null;
    @property(cc.Camera)
    protected transformCamera: cc.Camera = null;
    //#endregion

    //#region 材质球
    @property(cc.Material)
    protected levelMats: cc.Material[] = [];
    protected initMats() { }
    protected resetMats() { }
    protected setMatPathData(data, mats) {
        let len = this.totalRoadLen;
        let pathLen = cc.v4(len, 0, 0, 0);
        let pathState = cc.v4(1.0, 0.0, 0.0, 0.0);
        for (let i = mats.length - 1; i >= 0; --i) {
            let mat = mats[i];
            this.setMatData(mat, "pathLen", pathLen);
            let j = 0;
            this.setMatData(mat, "p11", data[j++]);
            this.setMatData(mat, "p12", data[j++]);
            this.setMatData(mat, "p21", data[j++]);
            this.setMatData(mat, "p22", data[j++]);
            this.setMatData(mat, "p31", data[j++]);
            this.setMatData(mat, "p32", data[j++]);
            this.setMatData(mat, "p41", data[j++]);
            this.setMatData(mat, "p42", data[j++]);
            this.setMatData(mat, "p51", data[j++]);
            this.setMatData(mat, "p52", data[j++]);
            this.setMatData(mat, "p61", data[j++]);
            this.setMatData(mat, "p62", data[j++]);
            this.setMatData(mat, "p71", data[j++]);
            this.setMatData(mat, "p72", data[j++]);
            this.setMatData(mat, "p81", data[j++]);
            this.setMatData(mat, "p82", data[j++]);
            this.setMatData(mat, "p91", data[j++]);
            this.setMatData(mat, "p92", data[j++]);
            this.setMatData(mat, "pa1", data[j++]);
            this.setMatData(mat, "pa2", data[j++]);
            this.setMatData(mat, "pEnd1", data[j++]);
            this.setMatData(mat, "pEnd2", data[j++]);

            this.setMatData(mat, "pathState", pathState);
        }
    }
    protected setMatData(mat: cc.Material, str: string, data) {
        let pass = mat.passes[0];
        let handle = pass.getHandle(str);
        pass.setUniform(handle, data);
    }
    //#endregion

    //#region 地面可收集零件的材质球
    @property(cc.Material)
    protected partMat: cc.Material = null;
    protected partPass: cc.renderer.Pass = null;
    protected partHandle: number = null;
    protected partFullData: cc.Vec4 = null;//x:0-玩家未收集满零件，零件包显示正常颜色，1-玩家已收集满，显示灰色
    protected initPartMat() {
        this.partPass = this.partMat.passes[0];
        this.partHandle = this.partPass.getHandle("partFullData");
        this.partFullData = cc.v4();
        this.partPass.getUniform(this.partHandle, this.partFullData);
        this.partFullData.x = 0;
    }
    protected resetPartMat() {
        this.partFullData.x = 0;
        this.applyPartMat();
    }
    protected applyPartMat() {
        // this.partPass.setUniform(this.partHandle, this.partFullData);
    }
    protected setPartFull() {
        this.partFullData.x = 1;
        this.applyPartMat();
    }
    protected setPartExitFull() {
        this.partFullData.x = 0;
        this.applyPartMat();
    }
    //#endregion

    //#region 路段
    @property(cc.Material)
    protected roadMat: cc.Material = null;
    @property(cc.Node)
    protected roadLayer: cc.Node = null;
    protected initRoad() {

    }
    protected resetRoad() {
        GlobalPool.putAllChildren(this.roadLayer, true);
    }
    protected setRoads(len: number) {
        let style = MapData.getSceneStyleData();
        let co = cc.color(style.RoadItem.color1);
        let d = [co.r / 255, co.g / 255, co.b / 255, 1];
        this.setMatData(this.roadMat, "color1", co);
        co = cc.color(style.RoadItem.color2);
        d = [co.r / 255, co.g / 255, co.b / 255, 1];
        this.setMatData(this.roadMat, "color2", co);
        co = cc.color(style.RoadItem.color3);
        d = [co.r / 255, co.g / 255, co.b / 255, 1];
        this.setMatData(this.roadMat, "color3", co);

        let l = RoadItem.roadItemLen;
        let startRoad = GlobalPool.get("RoadItem");
        startRoad.setPosition(0, 0, l - 0.1);
        this.roadLayer.addChild(startRoad);

        //截图ICON专用
        startRoad = GlobalPool.get("RoadItem");
        startRoad.setPosition(0, 0, l * 2 - 0.1);
        this.roadLayer.addChild(startRoad);
        startRoad = GlobalPool.get("RoadItem");
        startRoad.setPosition(0, 0, l * 3 - 0.1);
        this.roadLayer.addChild(startRoad);
        startRoad = GlobalPool.get("RoadItem");
        startRoad.setPosition(0, 0, l * 4 - 0.1);
        this.roadLayer.addChild(startRoad);

        //截图处理完毕

        let c = Math.floor(len / l) + 5;
        for (let i = 0; i < c; ++i) {
            let node = GlobalPool.get("RoadItem");
            node.setPosition(0, 0, -i * l - 0.1);
            this.roadLayer.addChild(node);
        }
    }
    //#endregion

    //#region 起点终点线
    @property(cc.Node)
    protected startLineLayer: cc.Node = null;
    protected startLine: cc.Node = null;
    protected endLine: cc.Node = null;
    protected initStartLine() {
        this.startLine = GlobalPool.get("StartLine");
        this.startLineLayer.addChild(this.startLine);
        this.startLine.setPosition(0, 0, GameConfig.GameRule.startLinePosZ);
        this.endLine = GlobalPool.get("StartLine");
        this.startLineLayer.addChild(this.endLine);
        this.endLine.active = false;
    }
    protected resetStartLine() {
        this.endLine.active = false;
    }
    protected setEndLine() {
        this.endLine.active = true;
        this.endLine.setPosition(0, 0, -this.totalRoadLen);
    }
    //#endregion

    //#region 终点门
    protected finishDoor: cc.Node = null;
    protected initFinishDoor() {
        this.loadFinishDoor(-1000);
    }
    protected loadFinishDoor(z: number) {
        Loader.loadBundleRes("LevelScene", "SinglePrefab/FinishDoor", (res) => {
            if (!this.finishDoor) {
                this.finishDoor = cc.instantiate(res);
                this.node.addChild(this.finishDoor);
                let w = Math.sin(GameConfig.GameRule.roadMaxRadian) * GameConfig.GameRule.roadHalfWidth;
                let s = w / 9.8 * 100;
                this.finishDoor.setScale(s, s, s);
            }
            let offsetY = Math.cos(GameConfig.GameRule.roadMaxRadian) * GameConfig.GameRule.roadHalfWidth;
            this.finishDoor.setPosition(0, -offsetY, z);
        }, cc.Prefab);
    }
    protected resetFinishDoor() {

    }
    protected setFinishDoor() {
        let z = -this.totalRoadLen;
        if (!this.finishDoor) {
            this.loadFinishDoor(z);
        } else {
            this.finishDoor.setPosition(0, this.finishDoor.position.y, z);
        }
        // console.log("终点门位置：", z);
    }
    //#endregion

    //#region 终点分数翻倍路段
    @property(cc.Material)
    protected scoreRoadMat: cc.Material = null;
    protected scoreRoadPass: cc.renderer.Pass = null;
    protected scoreRoadDataHandle: number = null;
    protected scoreRoadData: cc.Vec4 = null;
    protected scoreRoad: cc.Node = null;
    /**分数翻倍开始的Z坐标 */
    protected startScorePosZ: number = 0;
    /**当前到达的分数翻倍阶段的Z坐标 */
    protected curArrivedScoreZ: number = 0;
    protected scoreStepZ: number = 0;
    protected initScoreRoad() {
        this.scoreStepZ = GameConfig.GameRule.scoreRoadStepLen;
        this.curArrivedScoreZ = 0;
        this.scoreRoadPass = this.scoreRoadMat.passes[0];
        this.scoreRoadDataHandle = this.scoreRoadPass.getHandle("scoreData");
        this.scoreRoadData = cc.v4();
        this.scoreRoadPass.getUniform(this.scoreRoadDataHandle, this.scoreRoadData);
        this.loadScoreRoad(-1000);
    }
    protected loadScoreRoad(z: number) {
        Loader.loadBundleRes("LevelScene", "SinglePrefab/ScoreRoad", (res) => {
            if (!this.scoreRoad) {
                this.scoreRoad = cc.instantiate(res);
                this.node.addChild(this.scoreRoad);
                this.scoreRoad.getComponent(ScoreRoad).init();
            }
            this.scoreRoad.setPosition(0, 0, z);
            // this.scoreRoad.setPosition(0, 0, 0);
        }, cc.Prefab);
    }
    protected applyScoreRoadMat() {
        this.scoreRoadPass.setUniform(this.scoreRoadDataHandle, this.scoreRoadData);
    }
    protected resetScoreRoad() {
        this.curArrivedScoreZ = 0;
        this.scoreRoadData.x = 0;
        this.applyScoreRoadMat();
    }
    protected setScoreRoad() {
        let z = this.totalRoadLen;
        z = -10 - Math.ceil(z * 0.1) * 10;
        this.startScorePosZ = z;
        if (!this.scoreRoad) {
            this.loadScoreRoad(z);
        } else {
            this.scoreRoad.setPosition(0, 0, z);
            // this.scoreRoad.setPosition(0, 0, 0);
        }
    }
    protected updateScoreRoadData(z: number) {
        this.curArrivedScoreZ = z;
        this.scoreRoadData.x = z;
        this.applyScoreRoadMat();
    }
    //#endregion

    //#region 路面车辆提示标志
    //地面车辆标志
    @property(cc.Node)
    protected groundCarIconLayer: cc.Node = null;
    //侧面车辆标志
    @property(cc.Node)
    protected sideCarIconLayer: cc.Node = null;
    //侧面车辆标志牌
    @property(cc.Node)
    protected sideCarSignLayer: cc.Node = null;
    @property(cc.Material)
    protected groundCarIconMat: cc.Material = null;
    protected initGroundCarIcon() {

    }
    protected resetGroundCarIcon() {
        GlobalPool.putAllChildren(this.groundCarIconLayer);
        GlobalPool.putAllChildren(this.sideCarIconLayer);
        GlobalPool.putAllChildren(this.sideCarSignLayer);
        this.setCarIconType(2);
    }
    protected setGroundCarIcons(data) {
        let x = GameConfig.GameRule.roadHalfWidth;
        let y = -x * Math.sin(1.57 - GameConfig.GameRule.roadMaxRadian);
        x += RoadItem.houdu * 0.5;
        x *= Math.cos(1.57 - GameConfig.GameRule.roadMaxRadian);
        for (let i = 0, c = data.length; i < c; ++i) {
            let z = data[i].z + 15;
            for (let j = 0; j < 3; j++) {
                this.addGroundCarIcon(x, y, z);
                // z += GroundCarIcon.len;
                z += 10;
            }
        }
    }
    protected addGroundCarIcon(x, y, z: number) {
        let node = GlobalPool.get("GroundCarIcon");
        node.setPosition(0, 0, z + GroundCarIcon.len * 0.5);
        this.groundCarIconLayer.addChild(node);

        node = GlobalPool.get("SideCarSign");
        node.setPosition(x, y, z);
        this.sideCarSignLayer.addChild(node);
        node = GlobalPool.get("SideCarSign");
        node.setPosition(-x, y, z);
        this.sideCarSignLayer.addChild(node);

        y += 3.5;
        z += 0.3;
        node = GlobalPool.get("SideCarIcon");
        node.setPosition(x, y, z);
        this.sideCarIconLayer.addChild(node);
        node = GlobalPool.get("SideCarIcon");
        node.setPosition(-x, y, z);
        this.sideCarIconLayer.addChild(node);
    }
    /**设置车辆标志的车辆类型 */
    protected setCarIconType(type: number) {
        let pass = this.groundCarIconMat.passes[0];
        let handle = pass.getHandle("tilingOffset");
        let data = cc.v4();
        pass.getUniform(handle, data);
        data.z = (type - 1) * 0.33333333333;
        pass.setUniform(handle, data);
    }
    //#endregion

    //#region 浮空的石头和树
    @property(cc.Node)
    protected groundLayer: cc.Node = null;
    @property(cc.Node)
    protected treeLayer: cc.Node = null;
    protected initGroundLayer() {

    }
    protected resetGroundLayer() {
        GlobalPool.putAllChildren(this.groundLayer, true);
        GlobalPool.putAllChildren(this.treeLayer, true);
    }
    protected setShiTou(data) {
        let names = MapData.getSceneStyleData().ShiTouNames;
        if (names.length == 0) {
            return;
        }
        let tiChu = MapData.getSceneStyleData().id == 4 || MapData.getSceneStyleData().id == 2;
        let scale = MapData.getSceneStyleData().ShiTouScale;
        let nIndex = 0;
        let nCount = names.length;
        let offset = cc.v3();
        if (MapData.getSceneStyleData().id == 2) {
            offset.y = -3;
        }
        for (let i = 0, c = data.length; i < c; ++i) {
            let shiTous = TreeData[data[i]].shiTous;
            let offsetZ = -100 * i;
            for (let j = shiTous.length - 1; j >= 0; --j) {
                if (!!tiChu) {
                    let s = shiTous[j].s;
                    if (s.x !== s.y || s.x !== s.z || Math.random() < 0.3) {
                        continue;
                    }
                }
                this.addGround(shiTous[j].p, shiTous[j].s, offsetZ, names[nIndex], scale, offset);
                if (++nIndex >= nCount) {
                    nIndex = 0;
                }
            }
        }
    }
    protected setTrees(data) {
        let names = MapData.getSceneStyleData().TreeNames;
        if (names.length == 0) {
            return;
        }
        let tiChu = MapData.getSceneStyleData().id == 4 || MapData.getSceneStyleData().id == 2;
        let scale = MapData.getSceneStyleData().TreeScale;
        let nIndex = 0;
        let nCount = names.length;
        for (let i = 0, c = data.length; i < c; ++i) {
            let trees = TreeData[data[i]].trees;
            let offsetZ = -100 * i;
            for (let j = trees.length - 1; j >= 0; --j) {
                if (!!tiChu) {
                    let s = trees[j].s;
                    if (s.x !== s.y || s.x !== s.z) {
                        continue;
                    } else if (Math.random() < 0.3) {
                        continue;
                    }
                }
                this.addTree(trees[j].p, trees[j].s, offsetZ, names[nIndex], scale);
                if (++nIndex >= nCount) {
                    nIndex = 0;
                }
            }
        }
    }
    protected addGround(p, s, z, str, scale, offset) {
        let node = GlobalPool.get(str);
        node.setPosition(p.x + offset.x, p.y - 8 + offset.y, p.z + z + offset.z);
        node.setScale(s.x * scale, s.y * scale, s.z * scale);
        let tr = MapData.getTransform(p.z + z);
        node.eulerAngles = cc.v3(-tr.eulerAngles.x, 0, 0);
        this.groundLayer.addChild(node);
    }
    protected addTree(p, s, z, str, scale) {
        let node = GlobalPool.get(str);
        node.setPosition(p.x, p.y - 8, p.z + z);
        node.setScale(s.x * scale, s.y * scale, s.z * scale);
        let tr = MapData.getTransform(p.z + z);
        node.eulerAngles = cc.v3(-tr.eulerAngles.x, 0, 0);
        this.treeLayer.addChild(node);
    }
    //#endregion

    //#region 隧道
    @property(cc.Node)
    protected suiDaoLayer: cc.Node = null;
    protected initSuiDao() {

    }
    protected resetSuiDao() {
        GlobalPool.putAllChildren(this.suiDaoLayer);
    }
    protected setSuiDao(data) {
        for (let i = 0, c = data.length; i < c; ++i) {
            let node = GlobalPool.get("SuiDao");
            this.suiDaoLayer.addChild(node);
            node.setPosition(0, 0, data[i].z);
        }
    }
    //#endregion

    //#region 障碍物组
    @property(cc.Node)
    protected barrierGroupLayer: cc.Node = null;
    protected allBarrierGroups: BarrierGroup[] = [];
    protected initBarrierGroups() {

    }
    protected resetBarrierGroups() {
        GlobalPool.putAllChildren(this.barrierGroupLayer);
        this.allBarrierGroups = [];
    }
    protected setBarrierGroups(data, n) {
        // this.resetBarrierGroups();
        for (let i = 0, c = data.length; i < c; ++i) {
            let node = GlobalPool.get(n, data[i]);
            this.barrierGroupLayer.addChild(node);
            this.allBarrierGroups.push(node[customPoolScript]);
        }
    }
    //添加终点路段的障碍物
    protected addEndRoadBarrierGroup() {
        let z = this.totalRoadLen;
        z = -10 - Math.ceil(z * 0.1) * 10;
        let str1 = "WallBarrierGroup";
        for (let i = 0; i < 23; ++i) {
            let node = GlobalPool.get(str1, { z: z - 10 * i, r: 0 });
            this.barrierGroupLayer.addChild(node);
            this.allBarrierGroups.push(node[customPoolScript]);
        }
    }
    protected removeBarrierGroup(item) {
        let index = this.getElementIndexInArray(item, this.allBarrierGroups);
        this.allBarrierGroups.splice(index, 1);
        GlobalPool.put(item.node);
        this.emit(EventType.LevelEvent.removeBarrierGroupIndex, index);
    }
    //#endregion

    //#region AI
    @property(cc.Node)
    protected enemyLayer: cc.Node = null;
    protected allEnemies: Role[] = [];
    protected initAI() {

    }
    protected resetAI() {
        GlobalPool.putAllChildren(this.enemyLayer, true);
        this.allEnemies = [];
    }
    protected setAI(data) {
        for (let i = data.length - 1; i >= 0; --i) {
            let node = GlobalPool.get("Enemy", data[i]);
            this.enemyLayer.addChild(node);
            this.allEnemies.push(node[customPoolScript]);
            node[customPoolScript].enterLevel();
        }
        GlobalData.set(GlobalEnum.myGlobalDataType.enemies, this.allEnemies);
    }
    protected updateAI(dt: number) {
        this.runCustomUpdate(this.allEnemies, dt);
    }
    //#endregion

    //#region 车辆零件
    @property(cc.Node)
    protected carPartLayer: cc.Node = null;
    @property(cc.Node)
    protected carPartLayer2: cc.Node = null;
    protected allCarParts: BaseTransform[] = [];
    protected initCarParts() { }
    protected resetCarParts() {
        GlobalPool.putAllChildren(this.carPartLayer, true);
        GlobalPool.putAllChildren(this.carPartLayer2, true);
        this.allCarParts = [];
    }
    protected setCarParts(data) {
        for (let i = 0, c = data.length; i < c; ++i) {
            let node = GlobalPool.get("CarPart", data[i]);
            this.carPartLayer.addChild(node);
            this.allCarParts.push(node[customPoolScript]);
        }
    }
    protected setCarParts2(data) {
        for (let i = 0, c = data.length; i < c; ++i) {
            let node = GlobalPool.get("CarPart2", data[i]);
            this.carPartLayer2.addChild(node);
            this.allCarParts.push(node[customPoolScript]);
        }
    }
    //#endregion

    //#region 金币
    @property(cc.Node)
    protected goldLayer: cc.Node = null;
    protected allGolds: BaseTransform[] = [];
    protected initGolds() { }
    protected resetGolds() {
        GlobalPool.putAllChildren(this.goldLayer, true);
        this.allGolds = [];
    }
    protected setGolds(data) {
        for (let i = 0, c = data.length; i < c; ++i) {
            let node = GlobalPool.get("Gold", data[i]);
            this.goldLayer.addChild(node);
            this.allGolds.push(node[customPoolScript]);
        }
    }
    //#endregion

    //#region 地形
    @property(cc.Node)
    protected terrainLayer: cc.Node = null;
    protected allTerrains: Terrain[] = [];
    protected initTerrains() { }
    protected resetTerrains() {
        GlobalPool.putAllChildren(this.terrainLayer);
        this.allTerrains = [];
    }
    protected setTerrains(data) {
        for (let i = 0, c = data.length; i < c; ++i) {
            let node = GlobalPool.get("Terrain", data[i]);
            this.terrainLayer.addChild(node);
            this.allTerrains.push(node[customPoolScript]);
        }
        this.setTerrainMat(0, 1);
    }
    protected setTerrainMat(index: number, car: number) {
        let terrain = this.allTerrains[index];
        if (!!terrain) {
            terrain.setType(car);
        }
    }
    //#endregion

    //#region 碰撞检测
    protected checkColl() {
        this._checkCollPlayer(this.player);
        //AI:
        for (let i = this.allEnemies.length - 1; i >= 0; --i) {
            this._checkCollEnemy(this.allEnemies[i]);
        }
    }
    protected _checkCollPlayer(role: Role) {
        this._checkCollGroup(role, GlobalEnum.CollerType.barrierGroup, this.allBarrierGroups);
        this._checkCollGroup(role, GlobalEnum.CollerType.carPart, this.allCarParts);
        this._checkCollGroup(role, GlobalEnum.CollerType.changeCarQuad, this.allChangeCarQuad);
        this._checkCollGroup(role, GlobalEnum.CollerType.gold, this.allGolds);
        this._checkCollGroup(role, GlobalEnum.CollerType.terrain, this.allTerrains);
    }
    protected _checkCollEnemy(role: Role) {
        if (role.z - 10 < this.player.z) {
            this._checkCollGroup(role, GlobalEnum.CollerType.barrierGroup, this.allBarrierGroups);
            this._checkCollGroup(role, GlobalEnum.CollerType.terrain, this.allTerrains);
            this._checkCollGroup(role, GlobalEnum.CollerType.gold, this.allGolds);
        }
        this._checkCollGroup(role, GlobalEnum.CollerType.carPart, this.allCarParts);
        this._checkCollGroup(role, GlobalEnum.CollerType.changeCarQuad, this.allChangeCarQuad);
    }
    protected _checkCollGroup(role: Role, type: GlobalEnum.CollerType, arr: BaseTransform[]) {
        let minPtr = role.collPtr[type].min;
        if (minPtr >= arr.length) return;
        let p2 = minPtr;
        for (let i = minPtr; i < arr.length; ++i) {
            let item = arr[i];
            if (role.minZ > item.maxZ) {
                break;
            }
            if (!item.canColl) {
                continue;
            }
            if (role.maxZ < item.minZ) {
                p2 = i + 1;
                continue;
            }
            if (item.checkColl(role)) {
                item.onColl(role);
                role.onColl({ type: type, item: item });
            }
        }
        if (role.collPtr[type].min < p2) {
            role.collPtr[type].min = p2;
        }
    }
    //#endregion

    //#region 撞飞的障碍物
    @property(cc.Node)
    protected barrierLayer: cc.Node = null;
    protected allBarriers = [];
    protected initBarriers() {

    }
    protected resetBarriers() {
        GlobalPool.putAllChildren(this.barrierLayer);
        this.allBarriers = [];
    }
    protected addBarriers(data: cc.Node[]) {
        for (let i = data.length - 1; i >= 0; --i) {
            this.barrierLayer.addChild(data[i]);
            this.allBarriers.push(data[i][customPoolScript]);
        }
    }
    protected removeBarrier(item) {
        GlobalPool.put(item.node);
        this.removeElementInArray(item, this.allBarriers);
    }
    protected updateBarriers(dt: number) {
        this.runCustomUpdate(this.allBarriers, dt);
        this.cullBarrier();
    }
    protected cullBarrier() {
        let z = this.transformCameraNode.position.z + 10;
        for (let i = 0, c = this.allBarriers.length; i < c; ++i) {
            if (this.allBarriers[i].node.position.z > z) {
                GlobalPool.put(this.allBarriers[i].node);
                this.allBarriers.splice(i, 1);
                --i;
                --c;
            } else {
                break;
            }
        }
    }
    //#endregion

    //#region 给车辆变形的平面
    @property(cc.Node)
    protected changeCarQuadLayer: cc.Node = null;
    protected allChangeCarQuad: ChangeCarQuad[] = [];
    @property(cc.Material)
    protected changeCarMat: cc.Material = null;
    protected initChangeCarQuads() {
        this.setChangeCarMat([1, 2]);
    }
    protected resetChangeCarQuads() {
        GlobalPool.putAllChildren(this.changeCarQuadLayer, true);
        this.allChangeCarQuad = [];
        this.setChangeCarMat([1, 2]);
    }
    protected setChangeCarQuads(data) {
        for (let i = 0, c = data.length; i < c; ++i) {
            let node = GlobalPool.get("ChangeCarQuad", data[i]);
            this.changeCarQuadLayer.addChild(node);
            this.allChangeCarQuad.push(node[customPoolScript]);
        }
        this.setChangeCarMat([1, 2]);
        //满级试用时，第一道门不显示
        if (GlobalData.get(GlobalEnum.myGlobalDataType.tryMaxCar)) {
            this.changeCarQuadLayer.children[0].active = false;
        }
    }
    protected setChangeCarMat(cars: number[]) {
        let pass = this.changeCarMat.passes[0];
        let handle = pass.getHandle("carType");
        let data = cc.v4();
        pass.getUniform(handle, data);
        data.x = cars[0];
        data.y = cars[1];
        pass.setUniform(handle, data);
        for (let i = this.allChangeCarQuad.length - 1; i >= 0; --i) {
            this.allChangeCarQuad[i].cars = cars;
        }
    }
    //#endregion

    //#region 关卡全部物体的显隐管理
    protected allCullItems: cc.Node[] = [];
    protected firstCullItemPtr: number = 0;
    protected lastCullItemPtr: number = 0;
    protected maxCullItemPtr: number = 0;
    /**下一次需要检测时相机需要达到的Z坐标 */
    protected nextCullPosZ: number = 0;
    /**每次检测范围 */
    protected cullDis: number = 50;
    /**相机坐标与最后一个显示的物体的最小距离 */
    protected minCullDis: number = 150;
    protected initAllCullItems() {
        this.allCullItems = [];
        this.firstCullItemPtr = 0;
        this.lastCullItemPtr = 0;
        this.maxCullItemPtr = 0;
        this.nextCullPosZ = 0;
    }
    protected resetAllCullItems() {
        this.allCullItems = [];
        this.firstCullItemPtr = 0;
        this.lastCullItemPtr = 0;
        this.maxCullItemPtr = 0;
        this.nextCullPosZ = 0;
    }
    protected setAllCullItems(startCameraPosZ: number = 0) {
        let arr = [];
        arr = arr.concat(this.groundCarIconLayer.children);
        arr = arr.concat(this.sideCarIconLayer.children);
        arr = arr.concat(this.sideCarSignLayer.children);

        arr = arr.concat(this.groundLayer.children);
        arr = arr.concat(this.treeLayer.children);

        arr = arr.concat(this.barrierGroupLayer.children);
        arr = arr.concat(this.carPartLayer.children);
        arr = arr.concat(this.carPartLayer2.children);
        arr = arr.concat(this.goldLayer.children);

        if (!!this.finishDoor) {
            arr.push(this.finishDoor);
        }

        this.allCullItems = arr;
        this.allCullItems.sort((a, b) => {
            return b.position.z - a.position.z;
        });
        this.maxCullItemPtr = this.allCullItems.length - 1;
        // console.log("元素数量：", this.maxCullItemPtr + 1);
        let z1 = startCameraPosZ - this.minCullDis - this.cullDis;
        this.nextCullPosZ = z1 + this.minCullDis;
        let z2 = startCameraPosZ + 10;
        this.firstCullItemPtr = 0;
        for (let i = 0; i <= this.maxCullItemPtr; ++i) {
            if (this.allCullItems[i].position.z < z1) {
                this.allCullItems[i].active = false;
            } else if (this.allCullItems[i].position.z > z2) {
                this.allCullItems[i].active = false;
                this.firstCullItemPtr = i;
            } else {
                this.allCullItems[i].active = true;
                this.lastCullItemPtr = i;
            }
        }

        let data: any = {};
        data[GlobalEnum.CollerType.barrierGroup] = this.allBarrierGroups;
        data[GlobalEnum.CollerType.carPart] = this.allCarParts;
        data[GlobalEnum.CollerType.gold] = this.allGolds;
        GlobalData.set(GlobalEnum.myGlobalDataType.levelCollItems, data);
    }
    // protected startCullItems(startCameraPosZ: number = 0) {
    //     let z1 = startCameraPosZ - this.minCullDis - this.cullDis;
    //     let z2 = startCameraPosZ + 10;
    //     for (let i = 0; i <= this.maxCullItemPtr; ++i) {
    //         if (this.allCullItems[i].position.z < z1) {
    //             this.allCullItems[i].active = false;
    //         } else if (this.allCullItems[i].position.z > z2) {
    //             this.allCullItems[i].active = false;
    //             this.firstCullItemPtr = i;
    //         } else {
    //             this.allCullItems[i].active = true;
    //             this.lastCullItemPtr = i;
    //         }
    //     }
    // }
    protected updateCullItems(curPosZ: number) {
        if (curPosZ > this.nextCullPosZ) {
            return;
        }
        if (this.allCullItems.length == 0) {
            return;
        }
        let z = this.nextCullPosZ + 10;
        for (let i = this.firstCullItemPtr; i < this.lastCullItemPtr; ++i) {
            if (this.allCullItems[i].position.z > z) {
                this.allCullItems[i].active = false;
            } else {
                this.firstCullItemPtr = i;
                break;
            }
        }
        z = this.nextCullPosZ - this.minCullDis - this.cullDis;
        for (let i = this.lastCullItemPtr; i <= this.maxCullItemPtr; ++i) {
            if (this.allCullItems[i].position.z > z) {
                if (this.allCullItems[i].parent) {
                    this.allCullItems[i].active = true;
                }
            } else {
                this.lastCullItemPtr = i;
                break;
            }
        }
        this.nextCullPosZ -= this.cullDis;
    }
    /**镜头反向运动时的渲染剔除 */
    protected updateBackCullItems(curPosZ: number) {
        if (curPosZ < this.nextCullPosZ) {
            return;
        }
        let z = this.nextCullPosZ - this.minCullDis;
        for (let i = this.lastCullItemPtr; i >= 0; --i) {
            if (this.allCullItems[i].position.z < z) {
                this.allCullItems[i].active = false;
            } else {
                this.lastCullItemPtr = i;
                break;
            }
        }
        z = this.nextCullPosZ + this.cullDis;
        for (let i = this.firstCullItemPtr; i >= 0; --i) {
            if (this.allCullItems[i].position.z < z) {
                this.allCullItems[i].active = true;
            } else {
                this.firstCullItemPtr = i;
                break;
            }
        }
        this.nextCullPosZ += this.cullDis;
    }

    //#endregion

    //#region 车辆特效
    @property(cc.Node)
    protected streakLayer: cc.Node = null;
    protected initStreaks() {

    }
    protected resetStreaks() {
        GlobalPool.putAllChildren(this.streakLayer, true);
    }
    protected addStreaks(streaks: any[]) {
        for (let i = streaks.length - 1; i >= 0; --i) {
            this.streakLayer.addChild(streaks[i].node);
        }
    }
    protected removeStreaks(streaks) {
        for (let i = streaks.length - 1; i >= 0; --i) {
            GlobalPool.put(streaks[i].node);
        }
    }
    //#endregion

    //#region 彩带
    @property(cc.Node)
    protected caiDaiLayer: cc.Node = null;
    protected initCaiDai() {

    }
    protected resetCaiDai() {
        GlobalPool.putAllChildren(this.caiDaiLayer, true);
    }
    protected playCaiDai() {
        let node = GlobalPool.get("caidai");
        if (!node) {
            Loader.loadBundle("CommonEffect", () => {
                Loader.loadBundleRes("CommonEffect", "caidai", (res) => {
                    GlobalPool.createPool("caidai", res, "caidaiParticle");
                    let node2 = GlobalPool.get("caidai");
                    this.addCaiDai(node2);
                }, cc.Prefab, false);
            });
        } else {
            this.addCaiDai(node);
        }
    }
    protected addCaiDai(node) {
        let z = this.player.node.position.z;
        let x = GameConfig.GameRule.roadHalfWidth;
        let y = -x * Math.cos(GameConfig.GameRule.roadMaxRadian * 0.2);
        x = x * Math.sin(GameConfig.GameRule.roadMaxRadian * 0.2);
        this.caiDaiLayer.addChild(node);
        node.setPosition(x, y, z);
        node[customPoolScript].play();

        let node2 = GlobalPool.get("caidai");
        node2.setPosition(-x, y, z);
        this.caiDaiLayer.addChild(node2);
        node2[customPoolScript].play();

        this.emit(EventType.Common.AudioEvent.playEffect, GlobalEnum.AudioClip.caiDai, { volume: 0.5 });
    }
    //#endregion

    /**************************************************流程**************************************************/
    protected stepWaitTrySkin(dt: number) {

    }
    protected stepLevelPlaying(dt: number) {
        if (this.lobbyCameraPosZ >= 0) {
            this.resetCustomUpdateState();
            // this.startCullItems(0);
            this.once(EventType.LevelEvent.startJoy, this.onStartJoy, this);
            this.hideTouchMask();
            this.emit(EventType.LevelEvent.showHandAnim);
            if (GlobalData.get(GlobalEnum.myGlobalDataType.tryMaxCar)) {
                this.player.setPartFull();
            }
            return;
        }
        if (this.lobbyCameraPosZ > -20) {
            this.lobbyCameraPosZ -= this.lobbyCameraPosZ * 0.1;
            if (this.lobbyCameraPosZ > -0.1) {
                this.lobbyCameraPosZ = 0;
            }
        } else {
            this.lobbyCameraPosZ += dt * this.backSpeed;
        }
        this.camera.setPositionOnLobby(this.lobbyCameraPosZ);
        this.updateBackCullItems(this.lobbyCameraPosZ);
    }
    protected onStartJoy() {
        this.enterCustomUpdateState(GlobalEnum.LevelState.fighting);
        if (!GlobalData.get(GlobalEnum.myGlobalDataType.tryMaxCar)) {
            setTimeout(() => {
                this.emit(EventType.Common.DirectorEvent.pauseLevel);
                this.showUI(GlobalEnum.UI.trySkin);
            }, 300);
        }
    }

    //#region 战斗中
    protected stepPlayerFighting(dt: number) {
        this.updatePlayer(dt);
        this.updateCamera(dt);
        this.updateCullItems(this.transformCameraNode.position.z);
        this.updateAI(dt);
        this.updateBarriers(dt);
        this.checkColl();
        this.emit(EventType.LevelEvent.updateLevelProgress, (GameConfig.GameRule.startLinePosZ - this.player.z) / (this.totalRoadLen + GameConfig.GameRule.startLinePosZ));
        this.updateMingCi(dt);
        this.checkFinish();
    }
    protected updateMingCi(dt) {
        let c = 1;
        let z = this.player.node.position.z;
        for (let i = this.allEnemies.length - 1; i >= 0; --i) {
            if (this.allEnemies[i].node.position.z <= z) {
                c++;
            }
        }
        this.emit(EventType.LevelEvent.updateMingCi, c);
    }
    protected checkFinish() {
        if (this.player.node.position.z + this.totalRoadLen < 0) {
            GlobalData.set(GlobalEnum.myGlobalDataType.tryMaxCar, false);
            if (this.grade.arrivedEnemyCount > 0) {
                this.player.enterEndRoadLose();
                this.lose(this.getResultData());
                return;
            }
            this.player.moveToScoreLine();
            //todo:放胜利烟花
            // this.playCaiDai();
            // this.emit(EventType.Common.CtrlEvent.ctrlEnd);
            this.camera.enterScoreRoad();
            this.enterCustomUpdateState(GlobalEnum.LevelState.moveToScoreLine);
            this.emit(EventType.LevelEvent.showEndRoadTouchTip);
        }
    }

    //#endregion

    //#region 分数翻倍路段
    protected stepMoveToScoreStartLine(dt: number) {
        this.updatePlayer(dt);
        this.updateCamera(dt);
        this.updateBarriers(dt);
        if (this.player.node.position.z < this.startScorePosZ) {
            this.player.enterScoreRoad();
            this.updateScoreRoadData(this.startScorePosZ - this.scoreStepZ);
            this.curScoreRateInt = 0;
            this.enterCustomUpdateState(GlobalEnum.LevelState.moveOnScoreRoad);
        }
    }
    protected curScoreRateInt: number = 1;
    protected stepScoreRoad(dt: number) {
        this.updatePlayer(dt);
        this.checkCollEndBarrierGroup();
        this.updateBarriers(dt);
        this.updateCamera(dt);
        let z = this.player.node.position.z;
        if (this.curArrivedScoreZ > z) {
            // this.emit(EventType.Common.AudioEvent.playEffect, GlobalEnum.AudioClip.gold);
            this.emit(EventType.Common.SDKEvent.vibrateShort);
            this.updateScoreRoadData(this.curArrivedScoreZ - this.scoreStepZ);
            let r = Math.floor(this.getScoreRate());
            if (r > this.curScoreRateInt) {
                this.curScoreRateInt = r;
            }
            this.playCaiDai();
        }
        //玩家是否已掉落全部零件，停止前进
        if (this.player.getCurPartCount() <= 0) {
            this.playCaiDai();
            this.emit(EventType.Common.CtrlEvent.ctrlEnd);
            this.emit(EventType.LevelEvent.hideEndRoadTouchTip);
            this.win(this.getResultData());
        }
    }
    protected checkCollEndBarrierGroup() {
        let role = this.player;
        let type = GlobalEnum.CollerType.barrierGroup;
        let arr = this.allBarrierGroups;
        let minPtr = role.collPtr[type].min;
        if (minPtr >= arr.length) return;
        let p2 = minPtr;
        for (let i = minPtr; i < arr.length; ++i) {
            let item = arr[i];
            if (role.minZ > item.maxZ) {
                break;
            }
            if (!item.canColl) {
                continue;
            }
            if (role.maxZ < item.minZ) {
                p2 = i + 1;
                continue;
            }
            if (item.checkColl(role)) {
                item.onColl(role);
                // this.emit(EventType.Common.SDKEvent.vibrateShort);
            }
        }
        if (role.collPtr[type].min < p2) {
            role.collPtr[type].min = p2;
        }
    }
    protected getScoreRate() {
        return GameConfig.GameRule.scoreRoadStep * ((this.startScorePosZ - this.curArrivedScoreZ) / this.scoreStepZ - 1) + 1;
    }
    //#endregion

    //#region 胜利
    protected stepLevelWin(dt: number) {
        this.updateBarriers(dt);
        this.updateCamera(dt);
    }
    //#endregion

    //#region 失败
    protected stepLevelLose(dt: number) {
        this.updatePlayer(dt);
        this.checkCollEndBarrierGroup();
        this.updateBarriers(dt);
        this.updateAI(dt);
        this.updateCamera(dt);
    }
    //#endregion

    //#region 状态：首页中
    protected lobbyCameraPosZ: number = 0;
    protected lobbySpeed: number = -5;
    protected lobbySpeedScale: number = 1;
    protected stepLobby(dt: number) {
        this.lobbyCameraPosZ += dt * this.lobbySpeed * this.lobbySpeedScale;
        if (this.lobbySpeed > 0) {
            this.updateBackCullItems(this.lobbyCameraPosZ);
        } else {
            this.updateCullItems(this.lobbyCameraPosZ);
        }
        if (this.lobbyCameraPosZ > 0) {
            this.lobbyCameraPosZ = 0;
            this.lobbySpeed = -Math.abs(this.lobbySpeed);
        } else if (this.lobbyCameraPosZ + this.totalRoadLen < 0) {
            this.lobbyCameraPosZ = -this.totalRoadLen;
            this.lobbySpeed = Math.abs(this.lobbySpeed);
        }
        this.camera.setPositionOnLobby(this.lobbyCameraPosZ);
    }
    //#endregion

    /**************************************************事件**************************************************/
    protected onTestWin() {
        this.win();
    }
    protected onTestLose() {
        this.lose();
    }

    protected playerScale: number = 1;
    protected playerDeadPosition: cc.Vec3;
    /**玩家死亡 */
    protected onPlayerDead(data) {

    }

    protected canResurgence: boolean = true;
    /**玩家死亡动画结束 */
    protected onPlayerDeadAnimFinished() {
        let data = {
            canResurgence: this.canResurgence,
            lv: this.levelData.lv,
            gold: this.grade.gold,
        };
        this.canResurgence = false;
        this.lose(data);
        // this.emit(EventType.LevelEvent.playLoseAnim);
    }

    /**复活 */
    protected onResurgence() {
        if (Math.random() > 0.5) {
            this.emit(EventType.Common.AudioEvent.playBGM, GlobalEnum.AudioClip.BGM, true);
        } else {
            this.emit(EventType.Common.AudioEvent.playBGM, GlobalEnum.AudioClip.BGM2, true);
        }

        this.player.resurgence(this.playerDeadPosition);
        this.emit(EventType.Common.CtrlEvent.ctrlStart);
        this.enterCustomUpdateState(GlobalEnum.LevelState.playing);
    }

    /**UI胜利动画结束 */
    protected onWinAnimFinish() {
        this.win(this.getResultData());
    }
    /**UI失败动画结束 */
    protected onLoseAnimFinish() {
        this.lose();
    }


    /**玩家收集到金币 */
    protected onPlayerCollGold(gold) {
        this.grade.gold += 1;
        let p = gold.modelNode.getWorldPosition();
        let ui = GlobalData.get(GlobalEnum.Common.GlobalDataType.canvas);
        this.transformCamera.convertToUINode(p, ui, p);
        this.emit(EventType.LevelEvent.addGoldParticle, { p: p, gold: this.grade.gold });
    }

    //#region 零件
    protected onPlayerGetCarPart(data: { part, partCount: number, addCount: number }) {
        let p = data.part.modelNode.getWorldPosition();
        let ui = GlobalData.get(GlobalEnum.Common.GlobalDataType.canvas);
        this.transformCamera.convertToUINode(p, ui, p);
        this.emit(EventType.LevelEvent.playAddCarPartUIAnim, { p: p, partCount: data.partCount, addCount: data.addCount });
    }
    protected onPlayerDropCarPart(data: { part, partCount: number, subCount: number }) {
        let p = this.player.node.children[0].getWorldPosition();
        let ui = GlobalData.get(GlobalEnum.Common.GlobalDataType.canvas);
        this.transformCamera.convertToUINode(p, ui, p);
        this.emit(EventType.LevelEvent.playDropCarPartUIAnim, { p: p, partCount: data.partCount, subCount: data.subCount });
    }
    protected onPlayerPartFull() {
        this.setPartFull();
    }
    protected onPlayerPartExitFull() {
        this.setPartExitFull();
    }
    //#endregion

    //#region 车辆变形事件
    protected onPlayerCollChangeCarQuad(data: { index: number, car: number }) {
        if (data.index + 1 >= this.allChangeCarQuad.length) {
            return;
        }
        let cars = [1, 2, 3];
        let index = cars.indexOf(data.car);
        cars.splice(index, 1);
        if (Math.random() < 0.5) {
            let tempCar = cars[0];
            cars[0] = cars[1];
            cars[1] = tempCar;
        }
        if (cars[0] > cars[1]) {
            this.setCarIconType(cars[0]);
            this.setTerrainMat(data.index + 1, cars[1]);
        } else {
            this.setCarIconType(cars[1]);
            this.setTerrainMat(data.index + 1, cars[0]);
        }
        setTimeout(() => {
            this.setChangeCarMat(cars);
        }, 1000);
    }
    //#endregion

    protected onEnemyArrived(enemy) {
        // console.error("敌人计数");
        this.grade.arrivedEnemyCount++;
    }


    //#region 首页中展示关卡场景
    protected onShowMapFast() {
        this.lobbySpeedScale = 10;
    }
    protected onShowMapSlow() {
        this.lobbySpeedScale = 1;
    }
    //#endregion
}
